# -*- coding: utf8 -*-

import sys
import math
import os
from archive import BaseAdapter
from multiprocessing import cpu_count, Process
from time import sleep

import cairo

def _py2_poppler(file_name):
    import poppler
    from urllib import pathname2url
    return poppler.document_new_from_file("file://" + pathname2url(file_name), None)

def _py3_poppler(file_name):
    from gi.repository import Poppler
    from urllib.request import pathname2url
    return Poppler.Document.new_from_file("file://" + pathname2url(file_name), None)

def poppler_document(file_name):
    if sys.version_info[0] == 2:
        return _py2_poppler(file_name)
    if sys.version_info[0] == 3:
        return _py3_poppler(file_name)
    raise RuntimeError("Unsupported Pythno version: " + sys.version)


class PDFArchive(BaseAdapter):

    min_scale_width = 1200
    min_scale_height = 1920

    max_scale_width = 1200 * 4
    max_scale_height = 1920 * 4

    stop = False

    def get_files( self ):

        names = []

        document = poppler_document(self.file_name)

        n_pages = document.get_n_pages()

        for i in range(n_pages):
            names.append("%s.png" % i)

        return names

    def _render_page(self, save_to_file, document, page_n):

        page = document.get_page( page_n )

        psize = page.get_size()

        pw = int( psize[0] )
        ph = int( psize[1] )

        if pw * ph > self.max_scale_width * self.max_scale_height:

            scale = math.sqrt(self.max_scale_width * self.max_scale_height / pw / ph)

            pws = int( pw * scale )
            phs = int( ph * scale )

            pws -= pws % 4
            phs -= phs % 4

            if pws < 2:
                pws = 2
            if phs < 2:
                phs = 2
        elif pw * ph < self.min_scale_width * self.min_scale_height:

            scale = math.sqrt(self.min_scale_width * self.min_scale_height / pw / ph)

            pws = int( pw * scale )
            phs = int( ph * scale )

            pws -= pws % 4
            phs -= phs % 4

            if pws < 2:
                pws = 2
            if phs < 2:
                phs = 2
        else:
            pws = pw
            phs = ph
            scale = 1

        surface = cairo.ImageSurface(cairo.FORMAT_RGB24, pws, phs)
        ctx = cairo.Context(surface)
        mtx = cairo.Matrix()
        mtx.scale(scale, scale)
        ctx.set_matrix(mtx)
        page.render(ctx)

        surface.write_to_png( open(save_to_file, "wb") )

        del surface

        return

    def terminate(self):
        self.stop = True
        return


    def extract_pages(self, file_name, into_dir, page_start, page_end):
        try:
            document = poppler_document(file_name)
            n_pages = document.get_n_pages()
            for i in range(n_pages):

                if i < page_start or i >= page_end:
                    continue

                page_path = os.path.join(into_dir, "%s.png" % i)
                self._render_page(page_path, document, i)
        except:
            pass
        return 0


    def extract_files( self, into_dir):

        procs = []
        n_procs = cpu_count()

        try:
            document = poppler_document(self.file_name)
            n_pages = document.get_n_pages()

            if n_pages < n_procs:
                n_procs = n_pages

            dp = n_pages / n_procs

            for i in range(n_procs):

                page_start = i * dp
                page_end = (i + 1) * dp

                p = Process(target=self.extract_pages, args=(self.file_name, into_dir, page_start, page_end, ))

                p.start()
                procs.append(p)

                pass

            """
            for i in range(n_pages):

                if self.stop:
                    break

                page_path = os.path.join(into_dir, "%s.png" % i)
                self._render_page(page_path, document, i)
                """
        except:
            pass

        done = False
        while not done:
            done = True
            for i in range(n_procs):
                p = procs[i]
                if p.is_alive():
                    done = False
            sleep(0.1)

        return True
